package org.mybatis.generator.plugins;

import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.OutputUtilities;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.mybatis3.ListUtilities;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.utils.JavaMapperGeneratorHelper;
import org.mybatis.generator.utils.XMLMapperGeneratorHelper;

import java.util.List;
import java.util.Set;

/**
 * <b><code>BatchDeletePlugin</code></b>
 * <p/>
 * Description: 根据主键集合查询记录
 * <p/>
 * <b>Creation Time:</b> 2020/06/12.
 */
public class SelectByIdsPlugin extends PluginAdapter {

	private final static String SELECT_BY_IDS = "selectByIds";

	private final static String PARAMETER_NAME = "ids";

	@Override
	public boolean validate(List<String> list) {
		return true;
	}

	@Override
	public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass,
			IntrospectedTable introspectedTable) {
		if (introspectedTable.getTargetRuntime() == IntrospectedTable.TargetRuntime.MYBATIS3) {
			clientSelectByIdsMethodGenerated(interfaze, introspectedTable, context);
		}
		return super.clientGenerated(interfaze, topLevelClass, introspectedTable);
	}

	@Override
	public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
		if (introspectedTable.getTargetRuntime() == IntrospectedTable.TargetRuntime.MYBATIS3) {
			sqlMapSelectByIdsElementGenerated(document, introspectedTable);
		}
		return super.sqlMapDocumentGenerated(document, introspectedTable);
	}

	private void sqlMapSelectByIdsElementGenerated(Document document, IntrospectedTable introspectedTable) {
		String tableName = introspectedTable.getFullyQualifiedTableNameAtRuntime();

		String key = introspectedTable.getPrimaryKeyColumns().get(0).getActualColumnName();

		List<IntrospectedColumn> columnList = ListUtilities
				.removeIdentityAndGeneratedAlwaysColumns(introspectedTable.getAllColumns());

		String resultType;
		if (introspectedTable.getRules().generateResultMapWithBLOBs()) {
			resultType = introspectedTable.getResultMapWithBLOBsId();
		} else {
			resultType = introspectedTable.getBaseResultMapId();
		}

		XmlElement baseElement = XMLMapperGeneratorHelper.baseElementGenerator(XMLMapperGeneratorHelper.SELECT,
				SELECT_BY_IDS, FullyQualifiedJavaType.getNewListInstance().getFullyQualifiedName(),
				XMLMapperGeneratorHelper.RESULT_MAP, resultType);

		StringBuilder insertClause = new StringBuilder();
		insertClause.append("select ");
		for (int i = 0; i < columnList.size(); i++) {
			IntrospectedColumn introspectedColumn = columnList.get(i);
			insertClause.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));
			if (i != (columnList.size() - 1)) {
				insertClause.append(", ");
			}
			if (insertClause.length() > 80) {
				baseElement.addElement(new TextElement(insertClause.toString()));
				insertClause.setLength(0);
				OutputUtilities.xmlIndent(insertClause, 1);
			}
		}

		insertClause.append(String.format(" from %s where %s in (", tableName, key));
		baseElement.addElement(new TextElement(insertClause.toString()));

		XmlElement foreachElement = XMLMapperGeneratorHelper.baseForeachElementGenerator(PARAMETER_NAME, "item",
				"index", null);

		foreachElement.addAttribute(new Attribute("separator", ","));

		foreachElement.addElement(new TextElement("#{item}"));

		baseElement.addElement(foreachElement);

		baseElement.addElement(new TextElement(")"));

		document.getRootElement().addElement(baseElement);
	}

	private void clientSelectByIdsMethodGenerated(Interface interfaze, IntrospectedTable introspectedTable,
			Context context) {
		Set<FullyQualifiedJavaType> importedTypes = JavaMapperGeneratorHelper
				.importedBaseTypesGenerator(introspectedTable);
		FullyQualifiedJavaType returnType = FullyQualifiedJavaType.getNewListInstance();
		FullyQualifiedJavaType listType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());
		importedTypes.add(listType);
		returnType.addTypeArgument(listType);
		FullyQualifiedJavaType paramType = introspectedTable.getPrimaryKeyColumns().get(0).getFullyQualifiedJavaType();
		Method selectByIdsMethod = JavaMapperGeneratorHelper.methodGenerator(SELECT_BY_IDS, JavaVisibility.DEFAULT,
				returnType, new Parameter(new FullyQualifiedJavaType(paramType.getFullyQualifiedName() + "[]"),
						PARAMETER_NAME, "@Param(\"" + PARAMETER_NAME + "\")"));

		context.getCommentGenerator().addGeneralMethodComment(selectByIdsMethod, introspectedTable);
		interfaze.addImportedTypes(importedTypes);
		interfaze.addMethod(selectByIdsMethod);
	}
}